package com.example.easytraffic.core;

import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;

public class MultiThreadedTrafic implements Traffic{

	private ExecutorService executor;
	private int numberOfTheads;
	private Traffic traffic;
	
	public MultiThreadedTrafic(Traffic traffic, 
			int numberOfTheads) {
		super();
		this.traffic = traffic;
		this.numberOfTheads = numberOfTheads;
		this.executor = Executors.newFixedThreadPool(numberOfTheads);
	}

	public void run() {
		for (int i = 0; i < numberOfTheads; i++) {
			try {
				Future<?> future = executor.submit(traffic);
				future.get();
			} catch (ExecutionException e) {
				Throwable cause = e.getCause();
				if (cause instanceof TrafficEndedException) {
					stop();
					throw new TrafficEndedException();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (RejectedExecutionException e) {
				stop();
				throw new TrafficEndedException();
			}
		}
	}

	public void stop() {
		List<Runnable> awaitingTasks = executor.shutdownNow();
		if (awaitingTasks != null) {
			for (Runnable awaitingTask : awaitingTasks) {
				if (awaitingTask instanceof Traffic) {
					Traffic traffic = (Traffic) awaitingTask;
					traffic.stop();
				}
			}
		}
	}
}
